package com.txzt.gaea.business.plan.service.impl;

import com.alibaba.fastjson.JSON;
import com.txzt.gaea.base.service.DictDetailService;
import com.txzt.gaea.business.plan.domain.model.PlanInfo;
import com.txzt.gaea.business.plan.domain.model.PlanPack;
import com.txzt.gaea.business.plan.domain.query.PlanInfoQuery;
import com.txzt.gaea.business.plan.service.IPlanInfoService;
import com.txzt.gaea.business.plan.service.IPlanPackService;
import com.txzt.gaea.business.project.domain.model.ProjectInfo;
import com.txzt.gaea.business.project.service.IProjectInfoService;
import com.txzt.gaea.business.sequence.service.ISequenceService;
import com.txzt.gaea.business.util.TranslateUtil;
import com.txzt.gaea.common.base.service.impl.BaseServiceImpl;
import com.txzt.gaea.common.core.base.context.AdminUserContext;
import com.txzt.gaea.common.enums.*;
import com.txzt.gaea.common.exception.CustomException;
import com.txzt.gaea.flow.model.FlowBizStep;
import com.txzt.gaea.flow.service.FlowService;
import com.txzt.gaea.provide.service.FileInfoService;
import com.txzt.gaea.provide.vo.FileInfoVo;
import com.txzt.gaea.vo.AdminUserVO;
import org.beetl.sql.core.query.LambdaQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class PlanInfoServiceImpl extends BaseServiceImpl<PlanInfo> implements IPlanInfoService {

    private final static String SEPARATOR = "-";

    @Autowired
    private DictDetailService dictDetailService;
    @Autowired
    private ISequenceService sequenceService;
    @Autowired
    private FlowService flowService;
    @Autowired
    private IProjectInfoService projectInfoService;
    @Autowired
    private FileInfoService fileInfoService;
    @Autowired
    private IPlanPackService iPlanPackService;


    @Override
    public List<Map> statisticsPlanInfo() {
        return sqlManager.select("planInfo.planInfoStatistics",Map.class,null);
    }

    @Override
    public Long getTotal(){
        LambdaQuery<PlanInfo> planQuery = sqlManager.lambdaQuery(PlanInfo.class);
        return planQuery.andEq(PlanInfo::getIsDelete,IsDeleteEnum.NOTDELETE.getCode()).count();
    }

    @Override
    public Map getNumByStatus(){
        Map<String,Object> map = new HashMap<>();
        LambdaQuery<PlanInfo> planQuery = sqlManager.lambdaQuery(PlanInfo.class);
        map.put("planInit",planQuery.andEq(PlanInfo::getIsDelete,IsDeleteEnum.NOTDELETE.getCode())
                .andEq(PlanInfo::getPlanStatus,PlanStatus.INIT.getCode()).count());
        planQuery = sqlManager.lambdaQuery(PlanInfo.class);
        List<Integer> statusList = new ArrayList<>();
        statusList.add(PlanStatus.INIT.getCode());
        statusList.add(PlanStatus.CHECK.getCode());
        statusList.add(PlanStatus.PASS.getCode());
        statusList.add(PlanStatus.REJECT.getCode());
        map.put("planPass",planQuery.andEq(PlanInfo::getIsDelete,IsDeleteEnum.NOTDELETE.getCode())
                .andIn(PlanInfo::getPlanStatus,statusList).count());
        planQuery = sqlManager.lambdaQuery(PlanInfo.class);
        statusList = new ArrayList<>();
        statusList.add(PlanStatus.INIT.getCode());
        statusList.add(PlanStatus.CHECK.getCode());
        statusList.add(PlanStatus.PASS.getCode());
        map.put("planIssue",planQuery.andEq(PlanInfo::getIsDelete,IsDeleteEnum.NOTDELETE.getCode())
                .andIn(PlanInfo::getPlanStatus,statusList).count());
        planQuery = sqlManager.lambdaQuery(PlanInfo.class);
        statusList = new ArrayList<>();
        statusList.add(PlanStatus.INIT.getCode());
        statusList.add(PlanStatus.PASS.getCode());
        map.put("planWait",planQuery.andEq(PlanInfo::getIsDelete,IsDeleteEnum.NOTDELETE.getCode())
                .andIn(PlanInfo::getPlanStatus,statusList).count());
        planQuery = sqlManager.lambdaQuery(PlanInfo.class);
        map.put("planAssign",planQuery.andEq(PlanInfo::getIsDelete,IsDeleteEnum.NOTDELETE.getCode())
                .andEq(PlanInfo::getPlanStatus,PlanStatus.PASS.getCode()).count());
        List<Map> countList = sqlManager.select("planInfo.getCountByDept",Map.class,null);
        countList.forEach(item -> {
            item.put("deptName",TranslateUtil.getDepartmentName((Long)item.get("deptId")));
        });
        map.put("planList",countList);
        return map;
    }


    @Override
    public List<PlanInfo> getSelectedData(List<Long> idList) {
        return sqlManager.query(PlanInfo.class).andIn("id",idList).select();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int savePlanInfo(PlanInfo planInfo) {
        Calendar calendar = Calendar.getInstance();
        // 获取当前年
        int year = calendar.get(Calendar.YEAR);
        String code = dictDetailService.getCodeFlag("plan_type", planInfo.getPlanType());
//        String code = "Test";
        Integer sequence = sequenceService.getSequence("plan_type", planInfo.getPlanType());
        String projectNo = year + SEPARATOR + code + SEPARATOR + String.format("%03d", sequence);
        planInfo.setPlanYear(String.valueOf(year));
        planInfo.setProjectNo(projectNo);
        planInfo.setIsDelete(IsDeleteEnum.NOTDELETE.getCode());
        int count = sqlManager.insertTemplate(planInfo,true);
        Long flowBizId = null;
        if (PlanStatus.CHECK.getCode().equals(planInfo.getPlanStatus())) {
            //开启流程
            flowBizId = flowService.startFlowCustomizationOrStandard(planInfo.getId(), "tb_plan_info","plan_status",
                    PlanStatus.BACK.getCode(),PlanStatus.PASS.getCode(), PlanStatus.REJECT.getCode(),
                    PlanStatus.INIT.getCode(),FlowFlagEnum.MAKING_PLAN.getCode(),planInfo.getDeptId(), planInfo.getStepList(), planInfo.getFlowType());
        }
        //添加流程id
        if (null != flowBizId) {
            PlanInfo target = new PlanInfo();
            target.setId(planInfo.getId());
            target.setFlowId(flowBizId);
            sqlManager.updateTemplateById(target);
        }
        //文件处理
        if (null != planInfo.getPlanFile()){
            List<FileInfoVo> planFileList = JSON.parseArray(planInfo.getPlanFile(), FileInfoVo.class);
            fileInfoService.fileChange(null,planFileList,projectNo,1);
        }
        if (null != planInfo.getExpertFile()){
            List<FileInfoVo> expertFileList = JSON.parseArray(planInfo.getExpertFile(), FileInfoVo.class);
            fileInfoService.fileChange(null,expertFileList,projectNo,1);
        }
        return count;
    }

    @Override
    public int updateInfoOnly(PlanInfo planInfo) {
        PlanInfo oldOne = this.selectById(planInfo.getId());
        if (null != oldOne.getPlanFile() && null != planInfo.getPlanFile()){
            List<FileInfoVo> oldList = JSON.parseArray(oldOne.getPlanFile(), FileInfoVo.class);
            List<FileInfoVo> newList = JSON.parseArray(planInfo.getPlanFile(), FileInfoVo.class);
            fileInfoService.fileChange(oldList,newList,oldOne.getProjectNo(),1);
        }else if (null != planInfo.getPlanFile()){
            List<FileInfoVo> newList = JSON.parseArray(planInfo.getPlanFile(), FileInfoVo.class);
            fileInfoService.fileChange(null,newList,oldOne.getProjectNo(),1);
        }
        if (null != oldOne.getExpertFile() && null != planInfo.getExpertFile()){
            List<FileInfoVo> oldList = JSON.parseArray(oldOne.getExpertFile(), FileInfoVo.class);
            List<FileInfoVo> newList = JSON.parseArray(planInfo.getExpertFile(), FileInfoVo.class);
            fileInfoService.fileChange(oldList,newList,oldOne.getProjectNo(),1);
        }else if (null != planInfo.getExpertFile()){
            List<FileInfoVo> newList = JSON.parseArray(planInfo.getExpertFile(), FileInfoVo.class);
            fileInfoService.fileChange(null,newList,oldOne.getProjectNo(),1);
        }
        planInfo.setPlanStatus(null);
        return this.updateById(planInfo);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int updateInfo(PlanInfo planInfo){
        PlanInfo oldOne = this.selectById(planInfo.getId());
        if (null != oldOne.getPlanFile() && null != planInfo.getPlanFile()){
            List<FileInfoVo> oldList = JSON.parseArray(oldOne.getPlanFile(), FileInfoVo.class);
            List<FileInfoVo> newList = JSON.parseArray(planInfo.getPlanFile(), FileInfoVo.class);
            fileInfoService.fileChange(oldList,newList,oldOne.getProjectNo(),1);
        }else if (null != planInfo.getPlanFile()){
            List<FileInfoVo> newList = JSON.parseArray(planInfo.getPlanFile(), FileInfoVo.class);
            fileInfoService.fileChange(null,newList,oldOne.getProjectNo(),1);
        }
        if (null != oldOne.getExpertFile() && null != planInfo.getExpertFile()){
            List<FileInfoVo> oldList = JSON.parseArray(oldOne.getExpertFile(), FileInfoVo.class);
            List<FileInfoVo> newList = JSON.parseArray(planInfo.getExpertFile(), FileInfoVo.class);
            fileInfoService.fileChange(oldList,newList,oldOne.getProjectNo(),1);
        }else if (null != planInfo.getExpertFile()){
            List<FileInfoVo> newList = JSON.parseArray(planInfo.getExpertFile(), FileInfoVo.class);
            fileInfoService.fileChange(null,newList,oldOne.getProjectNo(),1);
        }
        // 若计划已存在流程且为提交审核，则代表为退回修改的数据，需执行流程的退回修改的下一步操作
        if (oldOne.getPlanStatus().equals(PlanStatus.BACK.getCode())) {
            //11-24 22：56 修改 --- 针对退回修改数据，判断是自定义/标准流程，分情况处理退回修改重新提交的情况（ O_o！都是bug）
//            flowService.nextStepOnlyForBackCusOrBack(planInfo.getFlowId(),planInfo.getStepList(), planInfo.getFlowType());
            flowService.nextStepOnlyForBackPlan(planInfo.getFlowId(), planInfo.getFlowType(),planInfo.getStepList());
        }
        //开启流程
        Long flowBizId = null;
        if (null == planInfo.getFlowId()){
            flowBizId = flowService.startFlowCustomizationOrStandard(planInfo.getId(), "tb_plan_info","plan_status",
                    PlanStatus.BACK.getCode(),PlanStatus.PASS.getCode(), PlanStatus.REJECT.getCode(),
                    PlanStatus.INIT.getCode(),FlowFlagEnum.MAKING_PLAN.getCode(),planInfo.getDeptId(), planInfo.getStepList(), planInfo.getFlowType());
            planInfo.setFlowId(flowBizId);
        }
        planInfo.setPlanStatus(PlanStatus.CHECK.getCode());
        return this.updateById(planInfo);
    }


    public List<PlanInfo> queryByPackId(Long packId){
       return sqlManager.query(PlanInfo.class).andEq("pack_id",packId).andEq("is_delete", IsDeleteEnum.NOTDELETE.getCode()).select();
    }

    @Override
    public PlanInfo selectPlanInfoById(Long id) {
        PlanInfo planInfo = sqlManager.single(PlanInfo.class,id);
        planInfo.setFlowStep(flowService.getFlowBizStep(planInfo.getFlowId()));
        planInfo.setPlanPack(iPlanPackService.selectById(planInfo.getPackId()));
        ProjectInfo projectInfo = projectInfoService.selectProjectInfoByPlanId(id);
        if (null != projectInfo){
            planInfo.setProjectStatus(projectInfo.getProjectStatus());
        }
        return planInfo;
    }

    @Override
    public int removePackIdById(List<Long> idList) {
        idList.forEach(item->{
            LambdaQuery<PlanInfo> query = sqlManager.lambdaQuery(PlanInfo.class);
            PlanInfo updateData = query.andEq(PlanInfo::getId,item).single();
            updateData.setPackId(null);
            updateData.setPlanStatus(PlanStatus.PASS.getCode());
            query = sqlManager.lambdaQuery(PlanInfo.class);
            query.andEq(PlanInfo::getId,item).update(updateData);
        });
        return 1;
    }

    @Override
    public int removePackIdByIdSingle(Long id) {
        PlanInfo old = this.selectById(id);
        if (null != old.getPackId()){
            PlanPack planPack = iPlanPackService.selectById(old.getPackId());
            if (null != planPack.getPackFile()){
                List<FileInfoVo> fileList = JSON.parseArray(planPack.getPackFile(), FileInfoVo.class);
                fileInfoService.deleteOneProjectNo(fileList,old.getProjectNo());
            }
        }
        List<Long> idList = new ArrayList<>(Collections.singletonList(id));
        return sqlManager.update("planInfo.removePackIdById",idList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int assignPlanInfo(String ids) {
        AdminUserVO adminUserVO = AdminUserContext.getUser();
        List<Long> idList = Arrays.stream(ids.split(",")).mapToLong(Long::valueOf).boxed().collect(Collectors.toList());
        AtomicInteger count = new AtomicInteger();
        idList.forEach(id ->{
            PlanInfo planInfo = new PlanInfo();
            planInfo.setId(id);
            planInfo.setPlanStatus(PlanStatus.PASS.getCode());
            planInfo.setAssignBy(adminUserVO.getId());
            planInfo.setAssignTime(new Date());
            count.addAndGet(sqlManager.updateTemplateById(planInfo));
            //新增项目
            PlanInfo source = sqlManager.single(PlanInfo.class, id);
            ProjectInfo target = new ProjectInfo();
            BeanUtils.copyProperties(source,target);
            target.setPlanId(source.getId());
            target.setFlowId(null);
            target.setProjectStatus(ProjectStatus.INIT.getCode());
            target.setIsDelete(IsDeleteEnum.NOTDELETE.getCode());
            projectInfoService.insertProjectInfo(target);
        });
        return count.get();
    }

    @Override
    public int revocationPlanInfo(PlanInfo planInfo) {
        PlanInfo info = sqlManager.single(PlanInfo.class,planInfo.getId());
        if (!info.getPlanStatus().equals(PlanStatus.CHECK.getCode())) {
            throw new CustomException("审核中数据不可撤回！");
        }
        LambdaQuery<FlowBizStep> stepQuery = sqlManager.lambdaQuery(FlowBizStep.class);
        List<FlowBizStep> stepList = stepQuery.andEq(FlowBizStep::getFlowBizId, planInfo.getFlowId())
                .orderBy("step_no asc").select();
        if (0 == stepList.size()) {
            throw new CustomException("撤回异常！");
        }else {
            if (null == stepList.get(0).getStepStatus()) {
//                PlanInfo target = new PlanInfo();
//                target.setId(info.getId());
//                target.setPlanStatus(PlanStatus.INIT.getCode());
//                target.setFlowId(null);
                info.setPlanStatus(PlanStatus.INIT.getCode());
                info.setFlowId(null);
                return sqlManager.updateById(info);
            }else {
                throw new CustomException("数据已审核不可撤回！");
            }
        }
    }


//    PlanInfo info = sqlManager.single(PlanInfo.class,planInfo.getId());
//        if (!info.getPlanStatus().equals(PlanStatus.CHECK.getCode())) {
//        throw new CustomException("非审核中数据不可撤回！");
//    }
//    FlowBiz flowBiz = sqlManager.single(FlowBiz.class,planInfo.getFlowId());
//    List<FlowBizStep> stepList = sqlManager.lambdaQuery(FlowBizStep.class)
//            .andEq(FlowBizStep::getFlowBizId, planInfo.getFlowId())
//            .orderBy("step_no asc").select();
//        if (0 == stepList.size()) {
//        throw new CustomException("撤回异常！");
//    }else {
//        if (null == stepList.get(flowBiz.getCurrentStep()).getStepStatus()) {
//            PlanInfo target = new PlanInfo();
//            target.setId(info.getId());
//            if (flowBiz.getCurrentStep() > 0) {
//                target.setPlanStatus(PlanStatus.BACK.getCode());
//            }else {
//                target.setPlanStatus(PlanStatus.INIT.getCode());
//            }
//            return sqlManager.updateTemplateById(target);
//        }else {
//            throw new CustomException("当前步骤已审核不可撤回！");


//    FlowBizStep backNextStep = null;
//    boolean flag = false;
//            for (FlowBizStep step:stepList){
//        if (flag) {
//            backNextStep = step;
//        }
//        if (FlowBizStatusEnum.BACK.getCode().equals(step.getStepStatus())) {
//            flag = true;
//        }
//    }
//            if (null != backNextStep ) {
//        if (null == backNextStep.getStepStatus()) {
//            PlanInfo target = new PlanInfo();
//            target.setId(info.getId());
//            target.setPlanStatus(PlanStatus.BACK.getCode());
//            return sqlManager.updateTemplateById(target);
//        }
//    }else {
//        if (null == stepList.get(0).getStepStatus()) {
//            PlanInfo target = new PlanInfo();
//            target.setId(info.getId());
//            target.setPlanStatus(PlanStatus.INIT.getCode());
//            return sqlManager.updateTemplateById(target);
//        }else {
//            throw new CustomException("数据已审核不可撤回！");
//        }

    @Override
    public int submitPlanInfo(Long id) {
        PlanInfo info = sqlManager.single(PlanInfo.class,id);
        if (PlanStatus.CHECK.getCode().equals(info.getPlanStatus())) {
            return 0;
        }
        //开启流程
        Long flowBizId = null;
        if (null == info.getFlowId()){
            flowBizId = flowService.startFlowUpgrade(info.getId(), "tb_plan_info","plan_status",
                    PlanStatus.INIT.getCode(),PlanStatus.PASS.getCode(), PlanStatus.REJECT.getCode(),
                    PlanStatus.INIT.getCode(),FlowFlagEnum.MAKING_PLAN.getCode(),info.getDeptId());
        }
        PlanInfo target = new PlanInfo();
        target.setId(info.getId());
        target.setPlanStatus(PlanStatus.CHECK.getCode());
        target.setFlowId(flowBizId);
        return sqlManager.updateTemplateById(target);
    }

    @Override
    public Long listCheckCount(PlanInfoQuery planInfoQuery) {
        List<Long> list = sqlManager .select("planInfo.selectPlanCheckCount", Long.class, planInfoQuery);
        return list.get(0);
    }
}
